package info.guardianproject.pixelknot.crypto; import android.util.Base64; import android.util.Log; import info.guardianproject.pixelknot.Constants.Logger; import java.io.UnsupportedEncodingException; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; public class Aes { public final static String LOG = Logger.AES; public static String DecryptWithPassword(String password, byte[] iv, byte[] message, byte[] salt) { String new_message = null; try { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256); SecretKey tmp = factory.generateSecret(spec); SecretKey secret_key = new SecretKeySpec(tmp.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, secret_key, new IvParameterSpec(iv)); new_message = new String(cipher.doFinal(message)); } catch (IllegalBlockSizeException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (BadPaddingException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (NoSuchAlgorithmException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (InvalidKeySpecException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (NoSuchPaddingException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (InvalidKeyException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } return new_message; } public static Map<String, String> EncryptWithPassword(String password, String message, byte[] salt) { Map<String, String> pack = null; String new_message = null; try { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256); SecretKey tmp = factory.generateSecret(spec); SecretKey secret_key = new SecretKeySpec(tmp.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); // TODO: follow up (https://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html) cipher.init(Cipher.ENCRYPT_MODE, secret_key); AlgorithmParameters params = cipher.getParameters(); String iv = Base64.encodeToString(params.getParameterSpec(IvParameterSpec.class).getIV(), Base64.DEFAULT); new_message = Base64.encodeToString(cipher.doFinal(message.getBytes("UTF-8")), Base64.DEFAULT); pack = new HashMap<String, String>(); pack.put(iv, new_message); } catch (IllegalBlockSizeException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (BadPaddingException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (UnsupportedEncodingException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (NoSuchAlgorithmException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (InvalidKeySpecException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (NoSuchPaddingException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (InvalidKeyException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } catch (InvalidParameterSpecException e) { Log.e(Logger.UI, e.toString()); e.printStackTrace(); } return pack; } }